﻿using System;
using System.Collections.Generic;
using System.Linq;
using BBCode.Nodes;

namespace BBCode.Tags.BBCodeTags
{
    /// <summary>
    /// ListItem Tag.
    /// </summary>
    public class ListItem : BBCode, ITag
    {
        private readonly string _openingTag;
        private readonly ITag[] _tagsToDodge;

        /// <summary>
        /// Initializes a new instance of the <see cref="ListItem"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="templateName">Name of the template.</param>
        /// <param name="tagsToDodge">The tags to dodge.</param>
        /// <param name="canBeNested">if set to <c>true</c> [can be nested].</param>
        /// <param name="priority">The priority.</param>
        public ListItem(string name, string templateName, ITag[] tagsToDodge, bool canBeNested = true, int priority = 0)
            : base(name, templateName, canBeNested, priority)
        {
            _openingTag = "[" + name + "]";
            _tagsToDodge = tagsToDodge;
        }

        /// <summary>
        /// Gets the nodes.
        /// </summary>
        /// <param name="innertext">The innertext.</param>
        /// <param name="node">The node.</param>
        /// <returns>The discovered nodes</returns>
        public IEnumerable<INode> GetNodes(string innertext, Nodes.BBCodeComplex node)
        {
            var nodes = new List<INode>();
            foreach (ITag tag in _tagsToDodge)
            {
                nodes.AddRange(tag.GetNodes(innertext));
            }

            var startingIndex = node.NodeIndex.Beginning + node.Opening.Length;

            IList<Nodes.BBCode> results = new List<Nodes.BBCode>();

            var index = innertext.IndexOf(_openingTag, StringComparison.OrdinalIgnoreCase);
            var openings = new List<int>();
            while (index != -1)
            {
                openings.Add(index);
                index = innertext.IndexOf(_openingTag, index + 1, StringComparison.OrdinalIgnoreCase);
            }

            foreach (var tempOpenings in from n in nodes let beginning = n.NodeIndex.Beginning let end = n.NodeIndex.End select (from o in openings
                                                                                                                                 where o < beginning || o > end
                                                                                                                                 select o))
            {
                openings = tempOpenings.ToList();
            }


            for (var i = 0; i < openings.Count; i++)
            {
                string nodeText;
                var nodeIndex = new NodeIndex {Beginning = startingIndex + openings[i]};
                if (openings.Count - 1 == i)
                {
                    //Laatste node
                    nodeText = innertext.Substring(openings[i]);
                    nodeIndex.End = startingIndex + innertext.Length;
                }
                else
                {
                    //Gewone node
                    nodeText = innertext.Substring(openings[i], openings[i + 1] - openings[i]);
                    nodeIndex.End = startingIndex + openings[i + 1];
                }

                //We have ourself a match!
                var bbCode = new Nodes.BBCode(this, nodeText, nodeIndex, "[*]", "");

                results.Add(bbCode);
            }

            return results;
        }
    }
}